﻿
/// <reference path="_namespace.js" />
/// <reference path="../BaseObject.js" />


/*****************************************************************************
Ajax library class definition. Kevin Robinson 2006.
Class: ajax.geometry.Math
/*****************************************************************************/

ajax.lang.addNamespace("ajax.geometry");
$imports("ajax.math.Vector3");

//-----------------------------------------------------------------------------
ajax.geometry.Math = function()
{
    ajax.geometry.Math.superConstructor.call(this);
    
    // Hook into Statics
    this.computeBoundingSphere  = ajax.geometry.Math.computeBoundingSphere;
    this.radianToDegree         = ajax.geometry.Math.radianToDegree;
    this.degreeToRadian         = ajax.geometry.Math.degreeToRadian;
}

//-----------------------------------------------------------------------------
ajax.lang.extend("ajax.geometry.Math", "ajax.BaseObject"); // Inherit
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
ajax.geometry.Math.prototype.toString = function()
{
    return "ajax.geometry.Math";
}

//-----------------------------------------------------------------------------
ajax.geometry.Math.cast = function(obj)
{///<returns type="ajax.geometry.Math"/>
    return obj;    
}

//-----------------------------------------------------------------------------
// Statics
//-----------------------------------------------------------------------------

ajax.geometry.Math.pi = 3.141593;
ajax.geometry.Math.piOver2 = ajax.geometry.Math.pi/2;
ajax.geometry.Math.piOver4 = ajax.geometry.Math.pi/4;
ajax.geometry.Math.twoPi   = ajax.geometry.Math.pi * 2;

ajax.geometry.Math.radianToDegree = function(radians)
{
    return radians * (180/Math.PI);
}

//-----------------------------------------------------------------------------
ajax.geometry.Math.degreeToRadian = function(degrees)
{
    return (degrees/180)*Math.PI;
}
    
//-----------------------------------------------------------------------------    
ajax.geometry.Math.radAngleBetweenNormals = function(normA, normB)
{///<param name="normA" type="ajax.math.Vector3"/>
 ///<param name="normB" type="ajax.math.Vector3"/>
    var cosA = ajax.math.Vector3.dot(normA, normB);
    return Math.acos(cosA);
}

//-----------------------------------------------------------------------------
ajax.geometry.Math.angleBetweenNormals = function(normA, normB)
{///<param name="normA" type="ajax.math.Vector3"/>
 ///<param name="normB" type="ajax.math.Vector3"/>
 
    // The Dot Product of two vectors is the Cossine of the angle between them * the LengthA * LengthB
    // The Dot of two NORMALISED vectors is the Cosine of the angle between them - 
    // as they have no length so it cancels out
    var cosA = ajax.math.Vector3.dot(normA, normB);
    return ajax.geometry.Math.radianToDegree(Math.acos(cosA));
}
    
//-----------------------------------------------------------------------------
ajax.geometry.Math.wrapValue = function(a, val)
{
    while (a >= val)
        a -= val;
    while (a < 0)
        a += val;
    return a;
}

//-----------------------------------------------------------------------------
ajax.geometry.Math.wrapAngle = function(a)
{    
    return ajax.geometry.Math.wrapValue(a, 360);
}

//-----------------------------------------------------------------------------
ajax.geometry.Math.square = function( f ) { return (f*f) ;}


//-----------------------------------------------------------------------------
ajax.geometry.Math.lineIntersectsSphere = function(v1, v2, vs, r)
{///<summary>This method returns an array of CVector3's one for each intersection, or an empty array if no intersections.</summary>
 ///<param name="v1" type="ajax.math.Vector3">Line Vector 1</param>
 ///<param name="v2" type="ajax.math.Vector3">Line Vector 2</param>
 ///<param name="vs" type="ajax.math.Vector3">Center point (Origin of sphere)</param>
 ///<param name="r" type="number">Radius of sphere</param>
    
     ret = [];
     var a;
     var b;
     var c;
     var mu;
     var i ;
     
     var gMath = ajax.geometry.Math;
     
     a = gMath.square(v2.x - v1.x) + gMath.square(v2.y - v1.y) + gMath.square(v2.z - v1.z);
     b =  2* ( (v2.x - v1.x)*(v1.x - vs.x)
          + (v2.y - v1.y)*(v1.y - vs.y)
          + (v2.z - v1.z)*(v1.z - vs.z) ) ;
     c =  gMath.square(vs.x) + gMath.square(vs.y) +
          gMath.square(vs.z) + gMath.square(v1.x) +
          gMath.square(v1.y) + gMath.square(v1.z) -
          2* ( vs.x*v1.x + vs.y*v1.y + vs.z*v1.z ) - gMath.square(r) ;
     i =   b * b - 4 * a * c ;
     
     if ( i < 0.0 )
         return ret;
     
     if ( i == 0.0 )
     {
         // one intersection
         ret = new Array(1);
         mu = -b/(2*a) ;
         ret[0] = new ajax.math.Vector3(
            v1.x + mu*(v2.x-v1.x),
            v1.y + mu*(v2.y-v1.y),
            v1.z + mu*(v2.z-v1.z)
            );
         return ret;
     }
     if ( i > 0.0 )
     {
         // two intersections
         ret = new Array(2);
         
          // first intersection
          mu = (-b + Math.sqrt( gMath.square(b) - 4*a*c )) / (2*a);
          ret[0] = new ajax.math.Vector3(
                  v1.x + mu*(v2.x-v1.x), 
                  v1.y + mu*(v2.y-v1.y),
                  v1.z + mu*(v2.z-v1.z)
                  );              

          // second intersection
          mu = (-b - Math.sqrt(gMath.square(b) - 4*a*c )) / (2*a);
          ret[1] = new ajax.math.Vector3(
                  v1.x + mu*(v2.x-v1.x), 
                  v1.y + mu*(v2.y-v1.y),
                  v1.z + mu*(v2.z-v1.z)
                  );       

          return ret;
     }   
     return ret;
}

//-----------------------------------------------------------------------------
ajax.geometry.Math.computeBoundingSphere = function(verts)
{
	var radius = 0;

	for (var i = 0; i < verts.length; i++)
	{
		var len = verts[i].length();
		if (len > radius)
			radius = len;
	}												 
	return radius;
}

//-----------------------------------------------------------------------------
ajax.geometry.Math.radianToDegree = function(radians)
{
	return radians * 180/Math.PI;
}

//-----------------------------------------------------------------------------
ajax.geometry.Math.degreeToRadian = function(degrees)
{
	return (degrees/180)*Math.PI;
}



// MS AJAX
ajax.geometry.Math.prototype.computeBoundingSphere  = ajax.geometry.Math.computeBoundingSphere;
ajax.geometry.Math.prototype.radianToDegree         = ajax.geometry.Math.radianToDegree;
ajax.geometry.Math.prototype.computeBoundingSphere  = ajax.geometry.Math.degreeToRadian;